package uk.co.mattroper.simplesvnlogviewer;

import java.util.Locale;
import java.text.*;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.io.*;

import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

/**
 *
 * @author Matthew Roper
 */
public class SubversionHistoryToSpreadsheet {
        
    /** Creates a new instance of SubversionHistoryToSpreadsheet */
    public SubversionHistoryToSpreadsheet() {}
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {	
        
        /* Get the URL: */
        System.out.print("Enter repository URL: ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String url = null;
        try {
            url = br.readLine();
        } catch (IOException ioe) {
            System.out.println("IO error trying to read the URL!");
            System.exit(1);
        }
        
        /* Get the username: */
        System.out.print("Enter your user name: ");
        
        String name = null;
        try {
            name = br.readLine();
        } catch (IOException ioe) {
            System.out.println("IO error trying to read your name!");
            System.exit(1);
        }
        
        /* Get the password: */      
        System.out.print("Enter your password: ");
        String password = null;
        try {
            password = br.readLine();
        } catch (IOException ioe) {
            System.out.println("IO error trying to read your password!");
            System.exit(1);
        }

        long startRevision = 0;
        long endRevision = -1;//HEAD (the latest) revision
        setupLibrary();
        SVNRepository repository = null;
        
        try {
            repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
        } catch (SVNException svne) {
            
            /* A malformed URL could be the cause of this exception. */
            System.err
                    .println("error while creating an SVNRepository for the location '"
                            + url + "': " + svne.getMessage());
            System.exit(1);
        }

        /* 
         * Skip this point for anonymous access
         */
        ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password);
        repository.setAuthenticationManager(authManager);

        /* Gets the latest revision number of the repository */
        try {
            endRevision = repository.getLatestRevision();
        } catch (SVNException svne) {
            System.err.println("error while fetching the latest repository revision: " + svne.getMessage());
            System.exit(1);
        }

        Collection logEntries = null;
        try {
            logEntries = repository.log(new String[] {""}, null,
                    startRevision, endRevision, true, true);
        } catch (SVNException svne) {
            System.out.println("error while collecting log information for '"
                    + url + "': " + svne.getMessage());
            System.exit(1);
        }
        
        /* prepare the spreadsheet */       
        OpenOfficeSpreadsheet spreadsheet = new OpenOfficeSpreadsheet();
        
        /*  output headers */
        try {
            spreadsheet.setCellValue(0, 0, "revision");
            spreadsheet.setCellValue(1, 0, "log message");
            spreadsheet.setCellValue(2, 0, "author");
            spreadsheet.setCellValue(3, 0, "date");
            spreadsheet.setCellValue(4, 0, "changed paths");
        } catch (Exception e) {}
        
        int row = 0;
        
        for (Iterator entries = logEntries.iterator(); entries.hasNext();) {
            
            row++;
            
            /* gets a next SVNLogEntry */
            SVNLogEntry logEntry = (SVNLogEntry) entries.next();
            
            /* obtain list of paths that were changed in that revision. */
            String pathOut = "";
            if (logEntry.getChangedPaths().size() > 0) {
                
                
                /* keys are changed paths */
                Set changedPathsSet = logEntry.getChangedPaths().keySet();

                for (Iterator changedPaths = changedPathsSet.iterator(); changedPaths
                        .hasNext();) {
                    
                    /* obtains a next SVNLogEntryPath */        
                    SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry
                            .getChangedPaths().get(changedPaths.next());
                    
                    pathOut += entryPath.getType()
                            + "	"
                            + entryPath.getPath()
                            + ((entryPath.getCopyPath() != null) ? " (from "
                                + entryPath.getCopyPath() + " revision "
                                + entryPath.getCopyRevision() + ")" : "")
                            + ((changedPaths.hasNext()) ?
                                    System.getProperty("line.separator") : "");
                }
            }
            
            /* format the date */  
            DateFormat dateFormatter;
            dateFormatter = DateFormat.getDateTimeInstance(
                    DateFormat.FULL, 
                    DateFormat.MEDIUM,
                    new Locale("en","GB"));
            String dateOut = dateFormatter.format(logEntry.getDate());
            
            /* output the revision attributes */
            try {
                spreadsheet.setCellValue(0, row, String.valueOf(logEntry.getRevision()));
                spreadsheet.setCellValue(1, row, logEntry.getMessage());
                spreadsheet.setCellValue(2, row, logEntry.getAuthor());
                spreadsheet.setCellValue(3, row, dateOut);
                spreadsheet.setCellValue(4, row, pathOut);
            } catch (Exception e) {}
        }
    }

    /*
     * Initializes the library to work with a repository via 
     * different protocols.
     */
    private static void setupLibrary() {
        /*
         * For using over http:// and https://
         */
        DAVRepositoryFactory.setup();
        /*
         * For using over svn:// and svn+xxx://
         */
        SVNRepositoryFactoryImpl.setup();
        
        /*
         * For using over file:///
         */
        FSRepositoryFactory.setup();
    }

}
